#define _CRT_SECURE_NO_WARNINGS
#include "SignVerify.h"


SignVerify::SignVerify()
{
}


SignVerify::~SignVerify()
{
}


BOOL SignVerify::GetCertificateInfo(char* pFilePath, std::string& strSubjectName)
{
	WCHAR szFileName[MAX_PATH];
	HCERTSTORE hStore = NULL;
	HCRYPTMSG hMsg = NULL;
	PCCERT_CONTEXT pCertContext = NULL;
	BOOL bResult = FALSE;
	DWORD dwEncoding = 0, dwContentType = 0, dwFormatType = 0;
	PCMSG_SIGNER_INFO pSignerInfo = NULL;
	DWORD dwSignerInfoSize = 0, dwDataSize = 0;
	CERT_INFO CertInfo;
	LPTSTR szName = NULL;
	BOOL bRet = FALSE;
	DWORD dwErrorCode = 0;

	__try
	{
#ifdef UNICODE
		lstrcpynW(szFileName, pFilePath, MAX_PATH);
#else
		if (mbstowcs(szFileName, pFilePath, MAX_PATH) == -1)
		{
			// TODO:: LOG_ERR
			dwErrorCode = ::GetLastError();
			__leave;
		}
#endif
		// Get message handle and store handle from the signed file.
		bResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE,
			szFileName,
			CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
			CERT_QUERY_FORMAT_FLAG_BINARY,
			0,
			&dwEncoding,
			&dwContentType,
			&dwFormatType,
			&hStore,
			&hMsg,
			NULL);
		if (!bResult)
		{
			// TODO:: LOG_ERR
			dwErrorCode = ::GetLastError();
			__leave;
		}

		// Get signer information size.
		bResult = CryptMsgGetParam(hMsg,
			CMSG_SIGNER_INFO_PARAM,
			0,
			NULL,
			&dwSignerInfoSize);
		if (!bResult)
		{
			// TODO:: LOG_ERR
			 dwErrorCode = ::GetLastError();
			__leave;
		}

		// Allocate memory for signer information.
		pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfoSize);
		if (!pSignerInfo)
		{
			// TODO:: LOG_ERR
			dwErrorCode = ::GetLastError();
			__leave;
		}

		// Get Signer Information.
		bResult = CryptMsgGetParam(hMsg,
			CMSG_SIGNER_INFO_PARAM,
			0,
			(PVOID)pSignerInfo,
			&dwSignerInfoSize);
		if (!bResult)
		{
			// TODO:: LOG_ERR
			 dwErrorCode = ::GetLastError();
			__leave;
		}

		// Search for the signer certificate in the temporary certificate store.
		CertInfo.Issuer = pSignerInfo->Issuer;
		CertInfo.SerialNumber = pSignerInfo->SerialNumber;

		pCertContext = CertFindCertificateInStore(hStore,
			ENCODING,
			0,
			CERT_FIND_SUBJECT_CERT,
			(PVOID)&CertInfo,
			NULL);
		if (!pCertContext)
		{
			// TODO:: LOG_ERR
			dwErrorCode = ::GetLastError();
			__leave;
		}

		dwDataSize = CertGetNameString(pCertContext,
			CERT_NAME_SIMPLE_DISPLAY_TYPE,
			0,
			NULL,
			NULL,
			0);
		if (!dwDataSize)
		{
			// TODO:: LOG_ERR
			dwErrorCode = ::GetLastError();
			__leave;
		}

		// Allocate memory for subject name.
		szName = (LPTSTR)LocalAlloc(LPTR, dwDataSize * sizeof(TCHAR));
		if (!szName)
		{
			// TODO:: LOG_ERR
			dwErrorCode = ::GetLastError();
			__leave;
		}

		// Get subject name.
		if (!(CertGetNameString(pCertContext,
			CERT_NAME_SIMPLE_DISPLAY_TYPE,
			0,
			NULL,
			szName,
			dwDataSize)))
		{
			// TODO:: LOG_ERR
			 dwErrorCode = ::GetLastError();
			__leave;
		}

		strSubjectName = (char*)szName;
		bRet = TRUE;
	}
	__finally
	{
		if (pSignerInfo != NULL)
		{
			LocalFree(pSignerInfo);
			pSignerInfo = NULL;
		}

		if (pCertContext != NULL)
		{
			CertFreeCertificateContext(pCertContext);
			pCertContext = NULL;
		}

		if (hStore != NULL)
		{
			CertCloseStore(hStore, 0);
			hStore = NULL;
		}

		if (hMsg != NULL)
		{
			CryptMsgClose(hMsg);
			hMsg = NULL;
		}

		if (szName != NULL)
		{
			LocalFree(szName);
			szName = NULL;
		}
	}

	return bRet;
}
